package com.hccl.service.parser;

import DM.DialogManager;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hccl.config.Constants;
import com.hccl.mongoEntities.ParserParamEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import static com.hccl.config.Constants.corpusPath;
import static com.hccl.config.Constants.jsonPath;

/**
 * Created by sunjia on 2018/4/21.
 */
@Service
public class ParserService {

    @Autowired
    ParserPool parserPool;
    @Autowired
    Constants constants;

    public Map<String,Object> sluParser(ParserParamEntity parserParam) throws Exception {

        Map<String,Object> resultMap = new HashMap();
        Parser parser = parserPool.take();
        if (parserParam.getGreeting() != null){
            parser.greeting(parserParam.getUserId());
        } else if (parserParam.getKeypad() != null) {
            parser.keypadParser(parserParam.getKeypad(), parserParam.getUserId(), parserParam.getTel());
        } else {
            parser.queryParser(parserParam.getLine(), parserParam.getUserId(), parserParam.getTel());
        }
        resultMap.put("currentSLU", parser.getCurrentSLU());
        resultMap.put("currentAction",parser.getCurrentAction());
        resultMap.put("currentGaz",parser.getCurrentGaz());
        updatekey(parser);
        return resultMap;
    }


    public void dmReset(ParserParamEntity parserParam){
        parserPool.getDialogManager().resetState(parserParam.getUserId());
    }

    public boolean update(){
        if (isUpdating()){
            System.out.println("同一时刻只允许一个更新");
            return false;
        }
        return updateAction();
    }

    //第一把锁，为了保护update同一时刻只执行一次
    private final static ReentrantLock locker = new ReentrantLock(false);

    //第二把锁,为了等待更新完成
    private final static ReentrantLock singallocker = new ReentrantLock(false);
    private final static Condition condition=singallocker.newCondition();

    //第三把锁，为了初始化map
    private final static ReentrantLock initlock = new ReentrantLock(false);

    //第四把锁，为了更新使用
    private final static ReentrantLock updatelock = new ReentrantLock(false);

    //线程安全的map
    public ConcurrentMap<Integer, Parser> parserMap = new ConcurrentHashMap<>();
    private boolean isUpdating(){
        return locker.isLocked();
    }

    private  boolean updateAction(){
        try {
            locker.lock();
            //增加一个初始化的读写锁
            try {
                initlock.lock();
                List<Parser> newParserList = parserPool.getNewParserList();
                for (Parser newParser:
                        newParserList) {
                    parserMap.put(newParser.getId(),newParser);
                }
                List<Parser> oldParserList = new ArrayList<Parser>();
                parserPool.getPool().drainTo(oldParserList);
                for (Parser oldparser:oldParserList){
                    parserPool.getPool().add(parserMap.get(oldparser.getId()));
                    parserMap.remove(oldparser.getId());
                }
            }catch (Exception e){

            }finally {
                initlock.unlock();
            }
            //等待更新完成
            if (!parserMap.isEmpty()){
                try {
                    singallocker.lock();
                    condition.await();
                }catch (Exception e){

                }
                finally {
                    singallocker.unlock();
                }
            }
        } catch (Exception e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        finally
        {
            locker.unlock();
        }
        return true;
    }

    public  void updatekey(Parser parser){
        if (!isUpdating()){
            parserPool.add(parser);
            return;
        }
        //为了保证初始化成功
        initlock.lock();
        initlock.unlock();
        if (parserMap.containsKey(parser.getId())){
            try {
                updatelock.lock();
                parserPool.add(parserMap.get(parser.getId()));
                parserMap.remove(parser.getId());
            }catch (Exception e){

            }finally {

                updatelock.unlock();
            }
        }
        if (parserMap.size()==0){
            //表示更新完成
            singallocker.lock();
            condition.signal();
            singallocker.unlock();
        }
    }

}
